Skip to content

mcp: HTTP Header Standardization for x-mcp-header#915

Open
guglielmo-san wants to merge 30 commits intomainfrom
guglielmoc/SEP-2243_http_standardization_2
Open

mcp: HTTP Header Standardization for x-mcp-header#915
guglielmo-san wants to merge 30 commits intomainfrom
guglielmoc/SEP-2243_http_standardization_2

Conversation

@guglielmo-san
Copy link
Copy Markdown
Contributor

@guglielmo-san guglielmo-san commented Apr 29, 2026

Description

Implements SEP-2243 (HTTP Header Standardization) for x-mcp-param custom header.

Fixes #905

…ttp_standardization_2

# Conflicts:
#	mcp/streamable.go
#	mcp/streamable_client_test.go
#	mcp/streamable_headers.go
#	mcp/streamable_headers_test.go
#	mcp/streamable_test.go
…_http_standardization_2' into guglielmoc/SEP-2243_http_standardization_2
@guglielmo-san guglielmo-san marked this pull request as ready for review April 30, 2026 13:27
@guglielmo-san guglielmo-san changed the title feat: HTTP Header Standardization for x-mcp-header mcp: HTTP Header Standardization for x-mcp-header May 5, 2026
Comment thread mcp/client.go
// Avoid sending nil over the wire.
params.Arguments = map[string]any{}
}
if tool := cs.getCachedTool(params.Name); tool != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also think how modelcontextprotocol/modelcontextprotocol#2549 will factor in into this solution.

Comment thread mcp/header_encoding.go Outdated
Comment thread mcp/header_encoding.go Outdated
Comment thread mcp/header_encoding.go Outdated
Comment thread mcp/header_encoding.go Outdated
Comment thread mcp/streamable_headers.go Outdated
Comment thread mcp/streamable_headers.go Outdated

bodyVal := unmarshalPrimitive(argRaw)
if bodyVal == nil {
continue
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC this is a situation where the header is present, but the value in arguments is not a primitive. Please add a comment explaining why it is ok to ignore this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it would probably be better to return an error. The SEP does not explicitly define this case but it makes more sense to me.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should also validate the schema on AddTool as well to make a situation where a server serves incorrect tool fail early?

Copy link
Copy Markdown
Contributor Author

@guglielmo-san guglielmo-san May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make sense, but it is not specified by the SEP. If the format of the Tool is wrong, then it will be filtered by the client and not returned by ListTools.
If the client still sends a non-primitive type then it will be caught here and return an error.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say we have some freedom how we construct SDK APIs and their behavior. IMO that would be a valuable change and it's always easier to remove such validation than introduce it after the release.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I added the check on the server, can we consider it a non-breaking change?

Comment thread mcp/streamable.go Outdated
Comment thread mcp/streamable.go Outdated
Comment thread mcp/client.go Outdated
if err != nil {
return nil, err
}
result.Tools = filterValidTools(result.Tools)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general this proposal adds HTTP specific functionality, so I'm a bit surprised that the spec requires general filtering. IMO ideally this change should be contained within streamable transport as much as possible. I'll ask on the SEP for clarification.

Copy link
Copy Markdown
Contributor

@maciej-kisiel maciej-kisiel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also some additional comments from AI review :)

Comment thread mcp/streamable_headers.go Outdated
Comment thread mcp/client.go
Comment thread mcp/streamable.go Outdated
Comment thread mcp/client.go
// Avoid sending nil over the wire.
params.Arguments = map[string]any{}
}
if tool := cs.getCachedTool(params.Name); tool != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also started wondering what should happen when the tools is not in the cache. It means that ListTools was not called before the call or the model has outdated information for some reason. Maybe we should proactively fail in that case? It likely should be consistent behavior across the SDKs, I will try to ask about it as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I also thought about it. I don't think we should fail on client if they do not want to call ListTools before. If the format is wrong it would fail on the server anyway, which has to be considered the ultimate source of truth

Comment thread mcp/streamable_headers.go Outdated
Comment thread mcp/streamable_headers.go Outdated

bodyVal := unmarshalPrimitive(argRaw)
if bodyVal == nil {
continue
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say we have some freedom how we construct SDK APIs and their behavior. IMO that would be a valuable change and it's always easier to remove such validation than introduce it after the release.

Comment thread mcp/streamable_headers.go Outdated
Comment thread mcp/streamable_headers.go Outdated
return nil
}
result := make(map[string]string)
for propName, propSchema := range props {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only comment I got on the SEP suggests that this shouldn't be limited to top level. Let's see if anyone confirms.

Comment thread mcp/streamable_headers.go Outdated
Comment thread mcp/streamable_headers.go
Comment thread mcp/server.go Outdated
Comment thread mcp/server.go Outdated
Comment thread mcp/streamable.go Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement SEP-2243 HTTP Standardization

2 participants